""" Library loading functions.

    A library is a collection of resource identifiers and their dependencies.
    It is used to create a registry of available resources.
"""

import os
from xml.etree import ElementTree as ET
from .. import debug, resource
from ..error import FormatError

VERSION = '0.02'

def load(path):
    """ Loads a resource library from an XML file.
    
        Unlike some other loaders, the object specified MUST be a path. File
        objects are not allowed. This is because the system must be able to
        determine the relative location of resources from the path given.
        
        Returns a dictionary of 'resourceID'->resInfoDict pairs suitable for use
        with sbak.resource.switch_library() and sbak.resource.add_library().
    """
    debug.message('Loading library "%s"...'%path)
    head,tail = os.path.split(path)
    tree = ET.parse(path)
    root = tree.getroot()
    # Fail if the version is not correct
    vers = root.get('version')
    if vers != VERSION:
        raise FormatError("Library version '%s' unsupported."%vers)
    # Parse the resource elements
    resElems = root.findall('resource')
    lib = {}
    for resElem in resElems:
        # Get a copy of the attributes so we can edit it without modifying the XML
        attrib = resElem.attrib.copy()
        # Make sure required attributes exist
        if 'id' not in attrib:
            raise FormatError("Library contains resource ref with no id.")
        ID = attrib['id']
        del attrib['id']
        if 'type' not in attrib:
            raise FormatError("Library contains resource ref with no type.")
        if 'src' not in attrib:
            raise FormatError("Library contains resource with no src.")
        # Remember, all resource paths are relative to the path from which the
        # file is being loaded!
        attrib['src'] = os.path.join(head,attrib['src'])

        # Add the agent description to the library
        lib[ID] = attrib
        
    return lib

def save(lib,path):
    """ Save a library (the kind returned by library.load) to file `path`. """
    debug.message("Saving library to %s.")
    # Create a builder
    builder = ET.TreeBuilder()
    # Start the root
    builder.start('library',{'version':VERSION})
    builder.data("\n    ")
    # Fill it with items from the library
    for k,v in lib.iteritems():
        v['id'] = k
        builder.start('resource',v)
        builder.end('resource').tail = "\n    "
    # Finish the root and save.
    ET.ElementTree(builder.end('library')).write(path)

def switch(path):
    """ Loads a library from the given file path and switches to it. """
    lib = load(path)
    resource.switch_library(lib)

def add(path):
    """ Loads a library from the given file path and adds it to the resource manager. """
    lib = load(path)
    resource.add_library(lib)